﻿///<reference path="../typings/tsd.d.ts" />
/*使用说明
该功能实现文件上传，进度显示以及取消
$("input[type='file']).autoFileUploader();
执行后，会包装一个div.autoFu  且在input前插入一个span标签。
上传时机：每次选择一个不同的文件时，就自动上传。绑定的change事件
*/
interface AutoFileUploaderOption {
    //文件上传的地址*/
    url?: string;
    /*显示文字 */
    text?: string;
    /**后缀过滤，用  |  分隔*/
    filter?: string;
}
module AUTO {
    /**文件ajax自动上传，带滚动，取消等功能，支持ie10+  */
    export class AutoFileUploader {
        private static DefaultClassName = "autoFu";
        private static DefaultEventNamespace = ".autoFuEvent";
        /**input file 自身*/
        private $file: JQuery;
        /*当前的ajax请求所对应的xmlhttprequest,用于随时取消上传*/
        private xhr: any;
        /*是否正在上传*/
        private isUping = false;
        private _opt: AutoFileUploaderOption = {
            url: '', text: '选择上传', filter: ''
        };
        constructor(element: Element, option: AutoFileUploaderOption) {
            var scope = this;
            this.$file = $(element);
            this._opt = $.extend(this._opt, option);
            if (!this.$file.parent().hasClass(AutoFileUploader.DefaultClassName)) {
                this.$file.wrap($(`<div class='${AutoFileUploader.DefaultClassName}'>`));
                this.$file.before(`<span class="btn btn-default btn-sm autoFuText">${this._opt.text}</span>`);
            } else {
                this.$file.off(AutoFileUploader.DefaultEventNamespace);
                this.$file.prev().text(this._opt.text);
            }
            if (!this.isSupport()) this.$file.prop("disabled", "disabled").attr("title", '当前浏览器不支持HTML5上传！')
                .prev().attr({ "disabled": "disabled" });
            this.bindEvent();
        }
        /**是否支持上传*/
        private isSupport(): boolean {
            return !!window["FormData"] &&
                !!$.ajaxSettings.xhr().upload;
        }
        /*执行校验后缀*/
        private CheckFile(filename: string): boolean {
            return !this._opt.filter || new RegExp(`(${this._opt.filter})$`).test(filename)
        }
        private bindEvent() {
            var scope = this;
            this.$file.on("change" + AutoFileUploader.DefaultEventNamespace, scope.upload.bind(scope));
            this.$file.on("click" + AutoFileUploader.DefaultEventNamespace, function () {
                /**判断状态*/
                if (scope.isUping) {
                    scope.xhr.abort();
                    scope.$file.prev().css("background", `#fff`).text(scope._opt.text);
                    scope.isUping = false;

                    scope.$file.trigger("canceled");
                    return false;
                }
            });
        }
        /**执行上传 */
        private upload() {
            var scope = this;
            var files: FileList = this.$file.prop("files");
            //如果没有文件，或者没通过验证后缀
            if (!files.length) return;
            if (_.some(files, function (f) {
                if (!scope.CheckFile(f.name)) {
                    console.log(f.name+"文件格式不正确！");
                    scope.$file.trigger("error", f.name);
                    return true;
                }
            })){return;}
            var fd = new FormData();
            fd.append("_file", files[0]);
            scope.isUping = true;
            $.ajax(this._opt.url, {
                data: fd,
                processData: false,
                type: "POST", contentType: false, dataType: 'json',
                xhr: function () {
                    scope.xhr = $.ajaxSettings.xhr();
                    if (scope.xhr.upload) {
                        scope.xhr.upload.addEventListener("progress", function (e: ProgressEvent) {
                            var per = Math.round((e.loaded / e.total) * 100) + "%";
                            scope.$file.prev().css("background", `linear-gradient(to right, #5cb85c ${per},#fff 0)`).text("取消");
                        }, false);
                        scope.xhr.upload.addEventListener("loadend", function (e: ProgressEvent) {
                            scope.$file.prev().css("background", `#fff`).text(scope._opt.text);
                            scope.isUping = false;
                        }, false);
                    }
                    return scope.xhr;
                }
            }).done(function (ret) {
                scope.$file.trigger("done", ret);
            }).fail(function () {
                console.log("上传时错误！");
                scope.$file.trigger("error", "上传时错误");
                return true;
            });
        }

    }
}